home *** CD-ROM | disk | FTP | other *** search
/ CU Amiga Super CD-ROM 24 / CU Amiga Magazine's Super CD-ROM 24 (1998)(EMAP Images)(GB)(Track 1 of 2)[!][issue 1998-07].iso / CUCD / Utilities / vim-5.1 / src / misc2.c < prev    next >
Encoding:
C/C++ Source or Header  |  1998-03-29  |  34.7 KB  |  1,642 lines

  1. /* vi:set ts=8 sts=4 sw=4:
  2.  *
  3.  * VIM - Vi IMproved    by Bram Moolenaar
  4.  *
  5.  * Do ":help uganda"  in Vim to read copying and usage conditions.
  6.  * Do ":help credits" in Vim to see a list of people who contributed.
  7.  */
  8.  
  9. /*
  10.  * misc2.c: Various functions.
  11.  */
  12.  
  13. #include "vim.h"
  14.  
  15. /*
  16.  * coladvance(col)
  17.  *
  18.  * Try to advance the Cursor to the specified column.
  19.  *
  20.  * return OK if desired column is reached, FAIL if not
  21.  */
  22.     int
  23. coladvance(wcol)
  24.     colnr_t        wcol;
  25. {
  26.     int        idx;
  27.     char_u    *ptr;
  28.     colnr_t    col;
  29.  
  30.     ptr = ml_get_curline();
  31.  
  32.     /* try to advance to the specified column */
  33.     idx = -1;
  34.     col = 0;
  35.     while (col <= wcol && *ptr)
  36.     {
  37.     ++idx;
  38.     /* Count a tab for what it's worth (if list mode not on) */
  39.     col += lbr_chartabsize(ptr, col);
  40.     ++ptr;
  41.     }
  42.     /*
  43.      * in insert mode it is allowed to be one char beyond the end of the line
  44.      */
  45.     if ((State & INSERT) && col <= wcol)
  46.     ++idx;
  47.     if (idx < 0)
  48.     curwin->w_cursor.col = 0;
  49.     else
  50.     curwin->w_cursor.col = idx;
  51.     if (col <= wcol)
  52.     return FAIL;        /* Couldn't reach column */
  53.     else
  54.     return OK;        /* Reached column */
  55. }
  56.  
  57. /*
  58.  * inc(p)
  59.  *
  60.  * Increment the line pointer 'p' crossing line boundaries as necessary.
  61.  * Return 1 when crossing a line, -1 when at end of file, 0 otherwise.
  62.  */
  63.     int
  64. inc_cursor()
  65. {
  66.     return inc(&curwin->w_cursor);
  67. }
  68.  
  69.     int
  70. inc(lp)
  71.     FPOS  *lp;
  72. {
  73.     char_u  *p = ml_get_pos(lp);
  74.  
  75.     if (*p != NUL)    /* still within line, move to next char (may be NUL) */
  76.     {
  77.     lp->col++;
  78.     return ((p[1] != NUL) ? 0 : 1);
  79.     }
  80.     if (lp->lnum != curbuf->b_ml.ml_line_count)        /* there is a next line */
  81.     {
  82.     lp->col = 0;
  83.     lp->lnum++;
  84.     return 1;
  85.     }
  86.     return -1;
  87. }
  88.  
  89. /*
  90.  * incl(lp): same as inc(), but skip the NUL at the end of non-empty lines
  91.  */
  92.     int
  93. incl(lp)
  94.     FPOS    *lp;
  95. {
  96.     int        r;
  97.  
  98.     if ((r = inc(lp)) == 1 && lp->col)
  99.     r = inc(lp);
  100.     return r;
  101. }
  102.  
  103. /*
  104.  * dec(p)
  105.  *
  106.  * Decrement the line pointer 'p' crossing line boundaries as necessary.
  107.  * Return 1 when crossing a line, -1 when at start of file, 0 otherwise.
  108.  */
  109.     int
  110. dec_cursor()
  111. {
  112.     return dec(&curwin->w_cursor);
  113. }
  114.  
  115.     int
  116. dec(lp)
  117.     FPOS  *lp;
  118. {
  119.     if (lp->col > 0)
  120.     {        /* still within line */
  121.     lp->col--;
  122.     return 0;
  123.     }
  124.     if (lp->lnum > 1)
  125.     {        /* there is a prior line */
  126.     lp->lnum--;
  127.     lp->col = STRLEN(ml_get(lp->lnum));
  128.     return 1;
  129.     }
  130.     return -1;            /* at start of file */
  131. }
  132.  
  133. /*
  134.  * decl(lp): same as dec(), but skip the NUL at the end of non-empty lines
  135.  */
  136.     int
  137. decl(lp)
  138.     FPOS    *lp;
  139. {
  140.     int        r;
  141.  
  142.     if ((r = dec(lp)) == 1 && lp->col)
  143.     r = dec(lp);
  144.     return r;
  145. }
  146.  
  147. /*
  148.  * Make sure curwin->w_cursor.lnum is valid.
  149.  */
  150.     void
  151. check_cursor_lnum()
  152. {
  153.     if (curwin->w_cursor.lnum > curbuf->b_ml.ml_line_count)
  154.     curwin->w_cursor.lnum = curbuf->b_ml.ml_line_count;
  155.     if (curwin->w_cursor.lnum <= 0)
  156.     curwin->w_cursor.lnum = 1;
  157. }
  158.  
  159. /*
  160.  * make sure curwin->w_cursor in on a valid character
  161.  */
  162.     void
  163. adjust_cursor()
  164. {
  165.     colnr_t len;
  166.  
  167.     check_cursor_lnum();
  168.  
  169.     len = STRLEN(ml_get_curline());
  170.     if (len == 0)
  171.     curwin->w_cursor.col = 0;
  172.     else if (curwin->w_cursor.col >= len)
  173.     curwin->w_cursor.col = len - 1;
  174. }
  175.  
  176. /*
  177.  * Make sure curwin->w_cursor is not on the NUL at the end of the line.
  178.  */
  179.     void
  180. adjust_cursor_col()
  181. {
  182.     if (curwin->w_cursor.col && gchar_cursor() == NUL)
  183.     --curwin->w_cursor.col;
  184. }
  185.  
  186. /*
  187.  * When curwin->w_leftcol has changed, adjust the cursor position.
  188.  * Return TRUE if the cursor was moved.
  189.  */
  190.     int
  191. leftcol_changed()
  192. {
  193.     long    lastcol;
  194.     colnr_t    s, e;
  195.     int        retval = FALSE;
  196.  
  197.     changed_cline_bef_curs();
  198.     lastcol = curwin->w_leftcol + Columns - (curwin->w_p_nu ? 8 : 0) - 1;
  199.     validate_virtcol();
  200.  
  201.     /*
  202.      * If the cursor is right or left of the screen, move it to last or first
  203.      * character.
  204.      */
  205.     if (curwin->w_virtcol > (colnr_t)lastcol)
  206.     {
  207.     retval = TRUE;
  208.     coladvance((colnr_t)lastcol);
  209.     }
  210.     else if (curwin->w_virtcol < curwin->w_leftcol)
  211.     {
  212.     retval = TRUE;
  213.     (void)coladvance(curwin->w_leftcol);
  214.     }
  215.  
  216.     /*
  217.      * If the start of the character under the cursor is not on the screen,
  218.      * advance the cursor one more char.  If this fails (last char of the
  219.      * line) adjust the scrolling.
  220.      */
  221.     getvcol(curwin, &curwin->w_cursor, &s, NULL, &e);
  222.     if (e > (colnr_t)lastcol)
  223.     {
  224.     retval = TRUE;
  225.     coladvance(s - 1);
  226.     }
  227.     else if (s < curwin->w_leftcol)
  228.     {
  229.     retval = TRUE;
  230.     if (coladvance(e + 1) == FAIL)    /* there isn't another character */
  231.     {
  232.         curwin->w_leftcol = s;    /* adjust w_leftcol instead */
  233.         changed_cline_bef_curs();
  234.     }
  235.     }
  236.  
  237.     redraw_later(NOT_VALID);
  238.     return retval;
  239. }
  240.  
  241. /**********************************************************************
  242.  * Various routines dealing with allocation and deallocation of memory.
  243.  */
  244.  
  245. /*
  246.  * Some memory is reserved for error messages and for being able to
  247.  * call mf_release_all(), which needs some memory for mf_trans_add().
  248.  */
  249. #define KEEP_ROOM 8192L
  250.  
  251. static void vim_strup __ARGS((char_u *p));
  252.  
  253. /*
  254.  * Note: if unsinged is 16 bits we can only allocate up to 64K with alloc().
  255.  * Use lalloc for larger blocks.
  256.  */
  257.     char_u *
  258. alloc(size)
  259.     unsigned        size;
  260. {
  261.     return (lalloc((long_u)size, TRUE));
  262. }
  263.  
  264. /*
  265.  * Allocate memory and set all bytes to zero.
  266.  */
  267.     char_u *
  268. alloc_clear(size)
  269.     unsigned        size;
  270. {
  271.     char_u *p;
  272.  
  273.     p = (lalloc((long_u)size, TRUE));
  274.     if (p != NULL)
  275.     (void)vim_memset(p, 0, (size_t)size);
  276.     return p;
  277. }
  278.  
  279. /*
  280.  * alloc() with check for maximum line length
  281.  */
  282.     char_u *
  283. alloc_check(size)
  284.     unsigned        size;
  285. {
  286. #if !defined(UNIX) && !defined(__EMX__)
  287.     if (sizeof(int) == 2 && size > 0x7fff)
  288.     {
  289.     EMSG("Line is becoming too long");
  290.     return NULL;
  291.     }
  292. #endif
  293.     return (lalloc((long_u)size, TRUE));
  294. }
  295.  
  296. /*
  297.  * Allocate memory like lalloc() and set all bytes to zero.
  298.  */
  299.     char_u *
  300. lalloc_clear(size, message)
  301.     long_u    size;
  302.     int        message;
  303. {
  304.     char_u *p;
  305.  
  306.     p = (lalloc(size, message));
  307.     if (p != NULL)
  308.     (void)vim_memset(p, 0, (size_t)size);
  309.     return p;
  310. }
  311.  
  312.     char_u *
  313. lalloc(size, message)
  314.     long_u        size;
  315.     int            message;
  316. {
  317.     char_u    *p;            /* pointer to new storage space */
  318.     static int    releasing = FALSE;  /* don't do mf_release_all() recursive */
  319.     int        try_again;
  320.  
  321.     if (size <= 0)
  322.     {
  323.     EMSGN("Internal error: lalloc(%ld, )", size);
  324.     return NULL;
  325.     }
  326. #if defined(MSDOS) && !defined(DJGPP)
  327.     if (size >= 0xfff0)        /* in MSDOS we can't deal with >64K blocks */
  328.     p = NULL;
  329.     else
  330. #endif
  331.  
  332.     /*
  333.      * If out of memory, try to release some memfile blocks.
  334.      * If some blocks are released call malloc again.
  335.      */
  336.     for (;;)
  337.     {
  338.     if ((p = (char_u *)malloc((size_t)size)) != NULL)
  339.     {
  340.         if (mch_avail_mem(TRUE) < KEEP_ROOM && !releasing)
  341.         {                    /* System is low... no go! */
  342.             vim_free((char *)p);
  343.             p = NULL;
  344.         }
  345.     }
  346.     /*
  347.      * Remember that mf_release_all() is being called to avoid an endless loop,
  348.      * because mf_release_all() may call alloc() recursively.
  349.      */
  350.     if (p != NULL || releasing)
  351.         break;
  352.     releasing = TRUE;
  353.     try_again = mf_release_all();
  354.     releasing = FALSE;
  355.     if (!try_again)
  356.         break;
  357.     }
  358.  
  359.     /*
  360.      * Avoid repeating the error message many times (they take 1 second each).
  361.      * Did_outofmem_msg is reset when a character is read.
  362.      */
  363.     if (message && p == NULL)
  364.     do_outofmem_msg();
  365.     return (p);
  366. }
  367.  
  368.     void
  369. do_outofmem_msg()
  370. {
  371.     if (!did_outofmem_msg)
  372.     {
  373.     emsg(e_outofmem);
  374.     did_outofmem_msg = TRUE;
  375.     }
  376. }
  377.  
  378. /*
  379.  * copy a string into newly allocated memory
  380.  */
  381.     char_u *
  382. vim_strsave(string)
  383.     char_u    *string;
  384. {
  385.     char_u    *p;
  386.     unsigned    len;
  387.  
  388.     len = STRLEN(string) + 1;
  389.     p = alloc(len);
  390.     if (p != NULL)
  391.     vim_memmove(p, string, (size_t)len);
  392.     return p;
  393. }
  394.  
  395.     char_u *
  396. vim_strnsave(string, len)
  397.     char_u    *string;
  398.     int        len;
  399. {
  400.     char_u    *p;
  401.  
  402.     p = alloc((unsigned)(len + 1));
  403.     if (p != NULL)
  404.     {
  405.     STRNCPY(p, string, len);
  406.     p[len] = NUL;
  407.     }
  408.     return p;
  409. }
  410.  
  411. /*
  412.  * like vim_strnsave(), but remove backslashes from the string.
  413.  */
  414.     char_u *
  415. vim_strnsave_esc(string, len)
  416.     char_u    *string;
  417.     int        len;
  418. {
  419.     char_u *p1, *p2;
  420.  
  421.     p1 = alloc((unsigned) (len + 1));
  422.     if (p1 != NULL)
  423.     {
  424.     STRNCPY(p1, string, len);
  425.     p1[len] = NUL;
  426.     for (p2 = p1; *p2; ++p2)
  427.         if (*p2 == '\\' && *(p2 + 1) != NUL)
  428.         STRCPY(p2, p2 + 1);
  429.     }
  430.     return p1;
  431. }
  432.  
  433. /*
  434.  * Same as vim_strsave(), but any characters found in esc_chars are preceded
  435.  * by a backslash.
  436.  */
  437.     char_u *
  438. vim_strsave_escaped(string, esc_chars)
  439.     char_u    *string;
  440.     char_u    *esc_chars;
  441. {
  442.     char_u    *p;
  443.     char_u    *p2;
  444.     char_u    *escaped_string;
  445.     unsigned    length;
  446.  
  447.     /*
  448.      * First count the number of backslashes required.
  449.      * Then allocate the memory and insert them.
  450.      */
  451.     length = 1;                /* count the trailing '/' and NUL */
  452.     for (p = string; *p; p++)
  453.     {
  454.     if (vim_strchr(esc_chars, *p) != NULL)
  455.         ++length;            /* count a backslash */
  456.     ++length;            /* count an ordinary char */
  457.     }
  458.     escaped_string = alloc(length);
  459.     if (escaped_string != NULL)
  460.     {
  461.     p2 = escaped_string;
  462.     for (p = string; *p; p++)
  463.     {
  464.         if (vim_strchr(esc_chars, *p) != NULL)
  465.         *p2++ = '\\';
  466.         *p2++ = *p;
  467.     }
  468.     *p2 = NUL;
  469.     }
  470.     return escaped_string;
  471. }
  472.  
  473. /*
  474.  * like vim_strsave(), but make all characters uppercase.
  475.  */
  476.     char_u *
  477. vim_strsave_up(string)
  478.     char_u    *string;
  479. {
  480.     char_u *p1;
  481.  
  482.     p1 = vim_strsave(string);
  483.     vim_strup(p1);
  484.     return p1;
  485. }
  486.  
  487. /*
  488.  * like vim_strnsave(), but make all characters uppercase.
  489.  */
  490.     char_u *
  491. vim_strnsave_up(string, len)
  492.     char_u    *string;
  493.     int        len;
  494. {
  495.     char_u *p1;
  496.  
  497.     p1 = vim_strnsave(string, len);
  498.     vim_strup(p1);
  499.     return p1;
  500. }
  501.  
  502.     static void
  503. vim_strup(p)
  504.     char_u    *p;
  505. {
  506.     char_u  *p2;
  507.     int        c;
  508.  
  509.     if (p != NULL)
  510.     {
  511.     p2 = p;
  512.     while ((c = *p2) != NUL)
  513.         *p2++ = TO_UPPER(c);
  514.     }
  515. }
  516.  
  517. /*
  518.  * copy a number of spaces
  519.  */
  520.     void
  521. copy_spaces(ptr, count)
  522.     char_u  *ptr;
  523.     size_t  count;
  524. {
  525.     size_t  i = count;
  526.     char_u  *p = ptr;
  527.  
  528.     while (i--)
  529.     *p++ = ' ';
  530. }
  531.  
  532. /*
  533.  * delete spaces at the end of a string
  534.  */
  535.     void
  536. del_trailing_spaces(ptr)
  537.     char_u *ptr;
  538. {
  539.     char_u  *q;
  540.  
  541.     q = ptr + STRLEN(ptr);
  542.     while (--q > ptr && vim_iswhite(q[0]) && q[-1] != '\\' &&
  543.                                q[-1] != Ctrl('V'))
  544.     *q = NUL;
  545. }
  546.  
  547. /*
  548.  * vim_strncpy()
  549.  *
  550.  * This is here because strncpy() does not guarantee successful results when
  551.  * the to and from strings overlap.  It is only currently called from nextwild()
  552.  * which copies part of the command line to another part of the command line.
  553.  * This produced garbage when expanding files etc in the middle of the command
  554.  * line (on my terminal, anyway) -- webb.
  555.  */
  556.     void
  557. vim_strncpy(to, from, len)
  558.     char_u *to;
  559.     char_u *from;
  560.     int len;
  561. {
  562.     int i;
  563.  
  564.     if (to <= from)
  565.     {
  566.     while (len-- && *from)
  567.         *to++ = *from++;
  568.     if (len >= 0)
  569.         *to = *from;    /* Copy NUL */
  570.     }
  571.     else
  572.     {
  573.     for (i = 0; i < len; i++)
  574.     {
  575.         to++;
  576.         if (*from++ == NUL)
  577.         {
  578.         i++;
  579.         break;
  580.         }
  581.     }
  582.     for (; i > 0; i--)
  583.         *--to = *--from;
  584.     }
  585. }
  586.  
  587. /*
  588.  * Isolate one part of a string option where parts are separated with commas.
  589.  * The part is copied into buf[maxlen].
  590.  * "*option" is advanced to the next part.
  591.  * The length is returned.
  592.  */
  593.     int
  594. copy_option_part(option, buf, maxlen, sep_chars)
  595.     char_u    **option;
  596.     char_u    *buf;
  597.     int        maxlen;
  598.     char    *sep_chars;
  599. {
  600.     int        len = 0;
  601.     char_u  *p = *option;
  602.  
  603.     /* skip '.' at start of option part, for 'suffixes' */
  604.     if (*p == '.')
  605.     buf[len++] = *p++;
  606.     while (*p && vim_strchr((char_u *)sep_chars, *p) == NULL)
  607.     {
  608.     /*
  609.      * Skip backslash before a separator character and space.
  610.      */
  611.     if (p[0] == '\\' && vim_strchr((char_u *)sep_chars, p[1]) != NULL)
  612.         ++p;
  613.     if (len < maxlen - 1)
  614.         buf[len++] = *p;
  615.     ++p;
  616.     }
  617.     buf[len] = NUL;
  618.  
  619.     p = skip_to_option_part(p);    /* p points to next file name */
  620.  
  621.     *option = p;
  622.     return len;
  623. }
  624.  
  625. /*
  626.  * replacement for free() that ignores NULL pointers
  627.  */
  628.     void
  629. vim_free(x)
  630.     void *x;
  631. {
  632.     if (x != NULL)
  633.     free(x);
  634. }
  635.  
  636. #ifndef HAVE_MEMSET
  637.     void *
  638. vim_memset(ptr, c, size)
  639.     void    *ptr;
  640.     int        c;
  641.     size_t  size;
  642. {
  643.     char *p = ptr;
  644.  
  645.     while (size-- > 0)
  646.     *p++ = c;
  647.     return ptr;
  648. }
  649. #endif
  650.  
  651. #ifdef VIM_MEMCMP
  652. /*
  653.  * Return zero when "b1" and "b2" are the same for "len" bytes.
  654.  * Return non-zero otherwise.
  655.  */
  656.     int
  657. vim_memcmp(b1, b2, len)
  658.     void    *b1;
  659.     void    *b2;
  660.     size_t  len;
  661. {
  662.     char_u  *p1 = (char_u *)b1, *p2 = (char_u *)b2;
  663.  
  664.     for ( ; len > 0; --len)
  665.     {
  666.     if (*p1 != *p2)
  667.         return 1;
  668.     ++p1;
  669.     ++p2;
  670.     }
  671.     return 0;
  672. }
  673. #endif
  674.  
  675. #ifdef VIM_MEMMOVE
  676. /*
  677.  * Version of memmove that handles overlapping source and destination.
  678.  * For systems that don't have a function that is guaranteed to do that (SYSV).
  679.  */
  680.     void
  681. vim_memmove(dst_arg, src_arg, len)
  682.     void    *src_arg, *dst_arg;
  683.     size_t  len;
  684. {
  685.     /*
  686.      * A void doesn't have a size, we use char pointers.
  687.      */
  688.     char *dst = dst_arg, *src = src_arg;
  689.  
  690.                     /* overlap, copy backwards */
  691.     if (dst > src && dst < src + len)
  692.     {
  693.     src +=len;
  694.     dst +=len;
  695.     while (len-- > 0)
  696.         *--dst = *--src;
  697.     }
  698.     else                /* copy forwards */
  699.     while (len-- > 0)
  700.         *dst++ = *src++;
  701. }
  702. #endif
  703.  
  704. #if (!defined(HAVE_STRCASECMP) && !defined(HAVE_STRICMP)) || defined(PROTO)
  705. /*
  706.  * Compare two strings, ignoring case.
  707.  * return 0 for match, 1 for difference
  708.  */
  709.     int
  710. vim_stricmp(s1, s2)
  711.     char    *s1;
  712.     char    *s2;
  713. {
  714.     for (;;)
  715.     {
  716.     if (TO_LOWER(*s1) != TO_LOWER(*s2))
  717.         return 1;                /* this character different */
  718.     if (*s1 == NUL)
  719.         break;                /* strings match until NUL */
  720.     ++s1;
  721.     ++s2;
  722.     }
  723.     return 0;                    /* strings match */
  724. }
  725. #endif
  726.  
  727. #if (!defined(HAVE_STRNCASECMP) && !defined(HAVE_STRNICMP)) || defined(PROTO)
  728. /*
  729.  * Compare two strings, for length "len", ignoring case.
  730.  * return 0 for match, 1 for difference
  731.  */
  732.     int
  733. vim_strnicmp(s1, s2, len)
  734.     char    *s1;
  735.     char    *s2;
  736.     size_t  len;
  737. {
  738.     while (len)
  739.     {
  740.     if (TO_LOWER(*s1) != TO_LOWER(*s2))
  741.         return 1;                /* this character different */
  742.     if (*s1 == NUL)
  743.         break;                /* strings match until NUL */
  744.     ++s1;
  745.     ++s2;
  746.     --len;
  747.     }
  748.     return 0;                    /* strings match */
  749. }
  750. #endif
  751.  
  752. /*
  753.  * Version of strchr() and strrchr() that handle unsigned char strings
  754.  * with characters above 128 correctly. Also it doesn't return a pointer to
  755.  * the NUL at the end of the string.
  756.  */
  757.     char_u  *
  758. vim_strchr(string, n)
  759.     char_u  *string;
  760.     int        n;
  761. {
  762.     char_u    *p;
  763.     int        c;
  764.  
  765.     p = string;
  766.     while ((c = *p) != NUL)
  767.     {
  768.     if (c == n)
  769.         return p;
  770.     ++p;
  771.     }
  772.     return NULL;
  773. }
  774.  
  775.     char_u  *
  776. vim_strrchr(string, n)
  777.     char_u  *string;
  778.     int        n;
  779. {
  780.     char_u  *retval = NULL;
  781.  
  782.     while (*string)
  783.     {
  784.     if (*string == n)
  785.         retval = string;
  786.     ++string;
  787.     }
  788.     return retval;
  789. }
  790.  
  791. /*
  792.  * Vim's version of strpbrk(), in case it's missing.
  793.  * Don't generate a prototype for this, causes problems when it's not used.
  794.  */
  795. #ifndef PROTO
  796. # ifndef HAVE_STRPBRK
  797. #  ifdef vim_strpbrk
  798. #   undef vim_strpbrk
  799. #  endif
  800.     char_u *
  801. vim_strpbrk(s, charset)
  802.     char_u  *s;
  803.     char_u  *charset;
  804. {
  805.     while (*s)
  806.     {
  807.     if (vim_strchr(charset, *s) != NULL)
  808.         return s;
  809.     ++s;
  810.     }
  811.     return NULL;
  812. }
  813. # endif
  814. #endif
  815.  
  816. /*
  817.  * Vim has its own isspace() function, because on some machines isspace()
  818.  * can't handle characters above 128.
  819.  */
  820.     int
  821. vim_isspace(x)
  822.     int        x;
  823. {
  824.     return ((x >= 9 && x <= 13) || x == ' ');
  825. }
  826.  
  827. /************************************************************************
  828.  * Functions for hanlding growing arrays.
  829.  */
  830.  
  831. /*
  832.  * Clear an allocated growing array.
  833.  */
  834.     void
  835. ga_clear(ga)
  836.     struct growarray *ga;
  837. {
  838.     vim_free(ga->ga_data);
  839.     ga_init(ga);
  840. }
  841.  
  842. /*
  843.  * Initialize a growing array.    Don't forget to set ga_itemsize and ga_growsize!
  844.  */
  845.     void
  846. ga_init(ga)
  847.     struct growarray *ga;
  848. {
  849.     ga->ga_data = NULL;
  850.     ga->ga_room = 0;
  851.     ga->ga_len = 0;
  852. }
  853.  
  854. /*
  855.  * Make room in growing array "ga" for at least "n" items.
  856.  * Return FAIL for failure, OK otherwise.
  857.  */
  858.     int
  859. ga_grow(ga, n)
  860.     struct growarray    *ga;
  861.     int            n;
  862. {
  863.     size_t        len;
  864.     char_u        *pp;
  865.  
  866.     if (ga->ga_room < n)
  867.     {
  868.     if (n < ga->ga_growsize)
  869.         n = ga->ga_growsize;
  870.     len = ga->ga_itemsize * (ga->ga_len + n);
  871.     pp = alloc_clear((unsigned)len);
  872.     if (pp == NULL)
  873.         return FAIL;
  874.     ga->ga_room = n;
  875.     if (ga->ga_data != NULL)
  876.     {
  877.         vim_memmove(pp, ga->ga_data,
  878.                       (size_t)(ga->ga_itemsize * ga->ga_len));
  879.         vim_free(ga->ga_data);
  880.     }
  881.     ga->ga_data = pp;
  882.     }
  883.     return OK;
  884. }
  885.  
  886. /************************************************************************
  887.  * functions that use lookup tables for various things, generally to do with
  888.  * special key codes.
  889.  */
  890.  
  891. /*
  892.  * Some useful tables.
  893.  */
  894.  
  895. static struct modmasktable
  896. {
  897.     int        mod_mask;        /* Bit-mask for particular key modifier */
  898.     char_u  name;        /* Single letter name of modifier */
  899. } mod_mask_table[] =
  900. {
  901.     {MOD_MASK_ALT,    (char_u)'M'},
  902.     {MOD_MASK_CTRL,    (char_u)'C'},
  903.     {MOD_MASK_SHIFT,    (char_u)'S'},
  904.     {MOD_MASK_2CLICK,    (char_u)'2'},
  905.     {MOD_MASK_3CLICK,    (char_u)'3'},
  906.     {MOD_MASK_4CLICK,    (char_u)'4'},
  907. #ifdef macintosh
  908.     {MOD_MASK_CMD,      (char_u)'D'},
  909. #endif
  910.     {0x0,        NUL}
  911. };
  912.  
  913. /*
  914.  * Shifted key terminal codes and their unshifted equivalent.
  915.  * Don't add mouse codes here, they are handled seperately!
  916.  */
  917. static char_u shifted_keys_table[] =
  918. {
  919. /*  shifted            unshifted  */
  920.     '&', '9',            '@', '1',        /* begin */
  921.     '&', '0',            '@', '2',        /* cancel */
  922.     '*', '1',            '@', '4',        /* command */
  923.     '*', '2',            '@', '5',        /* copy */
  924.     '*', '3',            '@', '6',        /* create */
  925.     '*', '4',            'k', 'D',        /* delete char */
  926.     '*', '5',            'k', 'L',        /* delete line */
  927.     '*', '7',            '@', '7',        /* end */
  928.     '*', '9',            '@', '9',        /* exit */
  929.     '*', '0',            '@', '0',        /* find */
  930.     '#', '1',            '%', '1',        /* help */
  931.     '#', '2',            'k', 'h',        /* home */
  932.     '#', '3',            'k', 'I',        /* insert */
  933.     '#', '4',            'k', 'l',        /* left arrow */
  934.     '%', 'a',            '%', '3',        /* message */
  935.     '%', 'b',            '%', '4',        /* move */
  936.     '%', 'c',            '%', '5',        /* next */
  937.     '%', 'd',            '%', '7',        /* options */
  938.     '%', 'e',            '%', '8',        /* previous */
  939.     '%', 'f',            '%', '9',        /* print */
  940.     '%', 'g',            '%', '0',        /* redo */
  941.     '%', 'h',            '&', '3',        /* replace */
  942.     '%', 'i',            'k', 'r',        /* right arrow */
  943.     '%', 'j',            '&', '5',        /* resume */
  944.     '!', '1',            '&', '6',        /* save */
  945.     '!', '2',            '&', '7',        /* suspend */
  946.     '!', '3',            '&', '8',        /* undo */
  947.     KS_EXTRA, (int)KE_S_UP,    'k', 'u',        /* up arrow */
  948.     KS_EXTRA, (int)KE_S_DOWN,    'k', 'd',        /* down arrow */
  949.  
  950.     KS_EXTRA, (int)KE_S_F1,    'k', '1',        /* F1 */
  951.     KS_EXTRA, (int)KE_S_F2,    'k', '2',
  952.     KS_EXTRA, (int)KE_S_F3,    'k', '3',
  953.     KS_EXTRA, (int)KE_S_F4,    'k', '4',
  954.     KS_EXTRA, (int)KE_S_F5,    'k', '5',
  955.     KS_EXTRA, (int)KE_S_F6,    'k', '6',
  956.     KS_EXTRA, (int)KE_S_F7,    'k', '7',
  957.     KS_EXTRA, (int)KE_S_F8,    'k', '8',
  958.     KS_EXTRA, (int)KE_S_F9,    'k', '9',
  959.     KS_EXTRA, (int)KE_S_F10,    'k', ';',        /* F10 */
  960.  
  961.     KS_EXTRA, (int)KE_S_F11,    'F', '1',
  962.     KS_EXTRA, (int)KE_S_F12,    'F', '2',
  963.     KS_EXTRA, (int)KE_S_F13,    'F', '3',
  964.     KS_EXTRA, (int)KE_S_F14,    'F', '4',
  965.     KS_EXTRA, (int)KE_S_F15,    'F', '5',
  966.     KS_EXTRA, (int)KE_S_F16,    'F', '6',
  967.     KS_EXTRA, (int)KE_S_F17,    'F', '7',
  968.     KS_EXTRA, (int)KE_S_F18,    'F', '8',
  969.     KS_EXTRA, (int)KE_S_F19,    'F', '9',
  970.     KS_EXTRA, (int)KE_S_F20,    'F', 'A',
  971.  
  972.     KS_EXTRA, (int)KE_S_F21,    'F', 'B',
  973.     KS_EXTRA, (int)KE_S_F22,    'F', 'C',
  974.     KS_EXTRA, (int)KE_S_F23,    'F', 'D',
  975.     KS_EXTRA, (int)KE_S_F24,    'F', 'E',
  976.     KS_EXTRA, (int)KE_S_F25,    'F', 'F',
  977.     KS_EXTRA, (int)KE_S_F26,    'F', 'G',
  978.     KS_EXTRA, (int)KE_S_F27,    'F', 'H',
  979.     KS_EXTRA, (int)KE_S_F28,    'F', 'I',
  980.     KS_EXTRA, (int)KE_S_F29,    'F', 'J',
  981.     KS_EXTRA, (int)KE_S_F30,    'F', 'K',
  982.  
  983.     KS_EXTRA, (int)KE_S_F31,    'F', 'L',
  984.     KS_EXTRA, (int)KE_S_F32,    'F', 'M',
  985.     KS_EXTRA, (int)KE_S_F33,    'F', 'N',
  986.     KS_EXTRA, (int)KE_S_F34,    'F', 'O',
  987.     KS_EXTRA, (int)KE_S_F35,    'F', 'P',
  988.  
  989.     KS_EXTRA, (int)KE_S_TAB,    KS_EXTRA, (int)KE_TAB,    /* TAB pseudo code*/
  990.  
  991.     NUL
  992. };
  993.  
  994. static struct key_name_entry
  995. {
  996.     int        key;    /* Special key code or ascii value */
  997.     char_u  *name;    /* Name of key */
  998. } key_names_table[] =
  999. {
  1000.     {' ',        (char_u *)"Space"},
  1001.     {TAB,        (char_u *)"Tab"},
  1002.     {K_TAB,        (char_u *)"Tab"},
  1003.     {NL,        (char_u *)"NL"},
  1004.     {NL,        (char_u *)"NewLine"},    /* Alternative name */
  1005.     {NL,        (char_u *)"LineFeed"},    /* Alternative name */
  1006.     {NL,        (char_u *)"LF"},    /* Alternative name */
  1007.     {CR,        (char_u *)"CR"},
  1008.     {CR,        (char_u *)"Return"},    /* Alternative name */
  1009.     {ESC,        (char_u *)"Esc"},
  1010.     {'|',        (char_u *)"Bar"},
  1011.     {'\\',        (char_u *)"Bslash"},
  1012.     {K_UP,        (char_u *)"Up"},
  1013.     {K_DOWN,        (char_u *)"Down"},
  1014.     {K_LEFT,        (char_u *)"Left"},
  1015.     {K_RIGHT,        (char_u *)"Right"},
  1016.  
  1017.     {K_F1,        (char_u *)"F1"},
  1018.     {K_F2,        (char_u *)"F2"},
  1019.     {K_F3,        (char_u *)"F3"},
  1020.     {K_F4,        (char_u *)"F4"},
  1021.     {K_F5,        (char_u *)"F5"},
  1022.     {K_F6,        (char_u *)"F6"},
  1023.     {K_F7,        (char_u *)"F7"},
  1024.     {K_F8,        (char_u *)"F8"},
  1025.     {K_F9,        (char_u *)"F9"},
  1026.     {K_F10,        (char_u *)"F10"},
  1027.  
  1028.     {K_F11,        (char_u *)"F11"},
  1029.     {K_F12,        (char_u *)"F12"},
  1030.     {K_F13,        (char_u *)"F13"},
  1031.     {K_F14,        (char_u *)"F14"},
  1032.     {K_F15,        (char_u *)"F15"},
  1033.     {K_F16,        (char_u *)"F16"},
  1034.     {K_F17,        (char_u *)"F17"},
  1035.     {K_F18,        (char_u *)"F18"},
  1036.     {K_F19,        (char_u *)"F19"},
  1037.     {K_F20,        (char_u *)"F20"},
  1038.  
  1039.     {K_F21,        (char_u *)"F21"},
  1040.     {K_F22,        (char_u *)"F22"},
  1041.     {K_F23,        (char_u *)"F23"},
  1042.     {K_F24,        (char_u *)"F24"},
  1043.     {K_F25,        (char_u *)"F25"},
  1044.     {K_F26,        (char_u *)"F26"},
  1045.     {K_F27,        (char_u *)"F27"},
  1046.     {K_F28,        (char_u *)"F28"},
  1047.     {K_F29,        (char_u *)"F29"},
  1048.     {K_F30,        (char_u *)"F30"},
  1049.  
  1050.     {K_F31,        (char_u *)"F31"},
  1051.     {K_F32,        (char_u *)"F32"},
  1052.     {K_F33,        (char_u *)"F33"},
  1053.     {K_F34,        (char_u *)"F34"},
  1054.     {K_F35,        (char_u *)"F35"},
  1055.  
  1056.     {K_XF1,        (char_u *)"F1"},
  1057.     {K_XF2,        (char_u *)"F2"},
  1058.     {K_XF3,        (char_u *)"F3"},
  1059.     {K_XF4,        (char_u *)"F4"},
  1060.  
  1061.     {K_HELP,        (char_u *)"Help"},
  1062.     {K_UNDO,        (char_u *)"Undo"},
  1063.     {K_BS,        (char_u *)"BS"},
  1064.     {K_BS,        (char_u *)"BackSpace"},    /* Alternative name */
  1065.     {K_INS,        (char_u *)"Insert"},
  1066.     {K_INS,        (char_u *)"Ins"},    /* Alternative name */
  1067.     {K_DEL,        (char_u *)"Del"},
  1068.     {K_DEL,        (char_u *)"Delete"},    /* Alternative name */
  1069.     {K_HOME,        (char_u *)"Home"},
  1070.     {K_END,        (char_u *)"End"},
  1071.     {K_PAGEUP,        (char_u *)"PageUp"},
  1072.     {K_PAGEDOWN,    (char_u *)"PageDown"},
  1073.     {K_KHOME,        (char_u *)"kHome"},
  1074.     {K_KEND,        (char_u *)"kEnd"},
  1075.     {K_KPAGEUP,        (char_u *)"kPageUp"},
  1076.     {K_KPAGEDOWN,    (char_u *)"kPageDown"},
  1077.  
  1078.     {K_MOUSE,        (char_u *)"Mouse"},
  1079.     {K_LEFTMOUSE,    (char_u *)"LeftMouse"},
  1080.     {K_LEFTDRAG,    (char_u *)"LeftDrag"},
  1081.     {K_LEFTRELEASE,    (char_u *)"LeftRelease"},
  1082.     {K_MIDDLEMOUSE,    (char_u *)"MiddleMouse"},
  1083.     {K_MIDDLEDRAG,    (char_u *)"MiddleDrag"},
  1084.     {K_MIDDLERELEASE,    (char_u *)"MiddleRelease"},
  1085.     {K_RIGHTMOUSE,    (char_u *)"RightMouse"},
  1086.     {K_RIGHTDRAG,    (char_u *)"RightDrag"},
  1087.     {K_RIGHTRELEASE,    (char_u *)"RightRelease"},
  1088.     {K_ZERO,        (char_u *)"Nul"},
  1089.     {0,            NULL}
  1090. };
  1091.  
  1092. #define KEY_NAMES_TABLE_LEN (sizeof(key_names_table) / sizeof(struct key_name_entry))
  1093.  
  1094. #ifdef USE_MOUSE
  1095. static struct mousetable
  1096. {
  1097.     int        pseudo_code;    /* Code for pseudo mouse event */
  1098.     int        button;        /* Which mouse button is it? */
  1099.     int        is_click;        /* Is it a mouse button click event? */
  1100.     int        is_drag;        /* Is it a mouse drag event? */
  1101. } mouse_table[] =
  1102. {
  1103.     {(int)KE_LEFTMOUSE,        MOUSE_LEFT,    TRUE,    FALSE},
  1104.     {(int)KE_LEFTDRAG,        MOUSE_LEFT,    FALSE,    TRUE},
  1105.     {(int)KE_LEFTRELEASE,    MOUSE_LEFT,    FALSE,    FALSE},
  1106.     {(int)KE_MIDDLEMOUSE,    MOUSE_MIDDLE,    TRUE,    FALSE},
  1107.     {(int)KE_MIDDLEDRAG,    MOUSE_MIDDLE,    FALSE,    TRUE},
  1108.     {(int)KE_MIDDLERELEASE,    MOUSE_MIDDLE,    FALSE,    FALSE},
  1109.     {(int)KE_RIGHTMOUSE,    MOUSE_RIGHT,    TRUE,    FALSE},
  1110.     {(int)KE_RIGHTDRAG,        MOUSE_RIGHT,    FALSE,    TRUE},
  1111.     {(int)KE_RIGHTRELEASE,    MOUSE_RIGHT,    FALSE,    FALSE},
  1112.     /* DRAG without CLICK */
  1113.     {(int)KE_IGNORE,        MOUSE_RELEASE,    FALSE,    TRUE},
  1114.     /* RELEASE without CLICK */
  1115.     {(int)KE_IGNORE,        MOUSE_RELEASE,    FALSE,    FALSE},
  1116.     {0,                0,        0,    0},
  1117. };
  1118. #endif /* USE_MOUSE */
  1119.  
  1120. /*
  1121.  * Return the modifier mask bit (MOD_MASK_*) which corresponds to the given
  1122.  * modifier name ('S' for Shift, 'C' for Ctrl etc).
  1123.  */
  1124.     int
  1125. name_to_mod_mask(c)
  1126.     int        c;
  1127. {
  1128.     int        i;
  1129.  
  1130.     for (i = 0; mod_mask_table[i].mod_mask; i++)
  1131.     if (TO_LOWER(c) == TO_LOWER(mod_mask_table[i].name))
  1132.         return mod_mask_table[i].mod_mask;
  1133.     return 0x0;
  1134. }
  1135.  
  1136. /*
  1137.  * Decide whether the given key code (K_*) is a shifted special
  1138.  * key (by looking at mod_mask).  If it is, then return the appropriate shifted
  1139.  * key code, otherwise just return the character as is.
  1140.  */
  1141.     int
  1142. check_shifted_spec_key(c)
  1143.     int        c;
  1144. {
  1145.     return simplify_key(c, &mod_mask);
  1146. }
  1147.  
  1148. /*
  1149.  * Check if if there is a special key code for "key" that include the
  1150.  * modifiers specified.
  1151.  */
  1152.     int
  1153. simplify_key(key, modifiers)
  1154.     int        key;
  1155.     int        *modifiers;
  1156. {
  1157.     int        i;
  1158.     int        key0;
  1159.     int        key1;
  1160.  
  1161.     if (*modifiers & MOD_MASK_SHIFT)
  1162.     {
  1163.     if (key == TAB)        /* TAB is a special case */
  1164.     {
  1165.         *modifiers &= ~MOD_MASK_SHIFT;
  1166.         return K_S_TAB;
  1167.     }
  1168.     key0 = KEY2TERMCAP0(key);
  1169.     key1 = KEY2TERMCAP1(key);
  1170.     for (i = 0; shifted_keys_table[i] != NUL; i += 4)
  1171.         if (key0 == shifted_keys_table[i + 2] &&
  1172.                         key1 == shifted_keys_table[i + 3])
  1173.         {
  1174.         *modifiers &= ~MOD_MASK_SHIFT;
  1175.         return TERMCAP2KEY(shifted_keys_table[i],
  1176.                            shifted_keys_table[i + 1]);
  1177.         }
  1178.     }
  1179.     return key;
  1180. }
  1181.  
  1182. /*
  1183.  * Return a string which contains the name of the given key when the given
  1184.  * modifiers are down.
  1185.  */
  1186.     char_u *
  1187. get_special_key_name(c, modifiers)
  1188.     int        c;
  1189.     int        modifiers;
  1190. {
  1191.     static char_u string[MAX_KEY_NAME_LEN + 1];
  1192.  
  1193.     int        i, idx;
  1194.     int        table_idx;
  1195.     char_u  *s;
  1196.  
  1197.     string[0] = '<';
  1198.     idx = 1;
  1199.  
  1200.     /*
  1201.      * Translate shifted special keys into unshifted keys and set modifier.
  1202.      */
  1203.     if (IS_SPECIAL(c))
  1204.     {
  1205.     for (i = 0; shifted_keys_table[i]; i += 4)
  1206.         if (       KEY2TERMCAP0(c) == shifted_keys_table[i]
  1207.             && KEY2TERMCAP1(c) == shifted_keys_table[i + 1])
  1208.         {
  1209.         modifiers |= MOD_MASK_SHIFT;
  1210.         c = TERMCAP2KEY(shifted_keys_table[i + 2],
  1211.                            shifted_keys_table[i + 3]);
  1212.         break;
  1213.         }
  1214.     }
  1215.  
  1216.     /* try to find the key in the special key table */
  1217.     table_idx = find_special_key_in_table(c);
  1218.  
  1219.     /*
  1220.      * When not a known special key, and not a printable character, try to
  1221.      * extract modifiers.
  1222.      */
  1223.     if (table_idx < 0 && !vim_isprintc(c) && (c & 0x80))
  1224.     {
  1225.     c &= 0x7f;
  1226.     modifiers |= MOD_MASK_ALT;
  1227.     /* try again, to find the un-alted key in the special key table */
  1228.     table_idx = find_special_key_in_table(c);
  1229.     }
  1230.     if (table_idx < 0 && !vim_isprintc(c) && c < ' ')
  1231.     {
  1232.     c += '@';
  1233.     modifiers |= MOD_MASK_CTRL;
  1234.     }
  1235.  
  1236.     /* translate the modifier into a string */
  1237.     for (i = 0; mod_mask_table[i].mod_mask; i++)
  1238.     if (modifiers & mod_mask_table[i].mod_mask)
  1239.     {
  1240.         string[idx++] = mod_mask_table[i].name;
  1241.         string[idx++] = (char_u)'-';
  1242.     }
  1243.  
  1244.     if (table_idx < 0)        /* unknown special key, output t_xx */
  1245.     {
  1246.     if (IS_SPECIAL(c))
  1247.     {
  1248.         string[idx++] = 't';
  1249.         string[idx++] = '_';
  1250.         string[idx++] = KEY2TERMCAP0(c);
  1251.         string[idx++] = KEY2TERMCAP1(c);
  1252.     }
  1253.     /* Not a special key, only modifiers, output directly */
  1254.     else
  1255.     {
  1256.         if (vim_isprintc(c))
  1257.         string[idx++] = c;
  1258.         else
  1259.         {
  1260.         s = transchar(c);
  1261.         while (*s)
  1262.             string[idx++] = *s++;
  1263.         }
  1264.     }
  1265.     }
  1266.     else        /* use name of special key */
  1267.     {
  1268.     STRCPY(string + idx, key_names_table[table_idx].name);
  1269.     idx = STRLEN(string);
  1270.     }
  1271.     string[idx++] = '>';
  1272.     string[idx] = NUL;
  1273.     return string;
  1274. }
  1275.  
  1276. /*
  1277.  * Try translating a <> name at (*srcp)[] to dst[].
  1278.  * Return the number of characters added to dst[], zero for no match.
  1279.  * If there is a match, srcp is advanced to after the <> name.
  1280.  * dst[] must be big enough to hold the result!
  1281.  */
  1282.     int
  1283. trans_special(srcp, dst)
  1284.     char_u  **srcp;
  1285.     char_u  *dst;
  1286. {
  1287.     int        modifiers;
  1288.     int        key;
  1289.     int        dlen = 0;
  1290.  
  1291.     key = find_special_key(srcp, &modifiers);
  1292.     if (key == 0)
  1293.     return 0;
  1294.  
  1295.     /* Put the appropriate modifier in a string */
  1296.     if (modifiers != 0)
  1297.     {
  1298.     dst[dlen++] = K_SPECIAL;
  1299.     dst[dlen++] = KS_MODIFIER;
  1300.     dst[dlen++] = modifiers;
  1301.     }
  1302.  
  1303.     if (IS_SPECIAL(key))
  1304.     {
  1305.     dst[dlen++] = K_SPECIAL;
  1306.     dst[dlen++] = KEY2TERMCAP0(key);
  1307.     dst[dlen++] = KEY2TERMCAP1(key);
  1308.     }
  1309.     else
  1310.     dst[dlen++] = key;
  1311.  
  1312.     return dlen;
  1313. }
  1314.  
  1315. /*
  1316.  * Try translating a <> name at (*srcp)[], return the key and modifiers.
  1317.  * srcp is advanced to after the <> name.
  1318.  * returns 0 if there is no match.
  1319.  */
  1320.     int
  1321. find_special_key(srcp, modp)
  1322.     char_u    **srcp;
  1323.     int        *modp;
  1324. {
  1325.     char_u  *last_dash;
  1326.     char_u  *end_of_name;
  1327.     char_u  *src;
  1328.     char_u  *bp;
  1329.     int        modifiers;
  1330.     int        bit;
  1331.     int        key;
  1332.  
  1333.     src = *srcp;
  1334.     if (src[0] != '<')
  1335.     return 0;
  1336.  
  1337.     /* Find end of modifier list */
  1338.     last_dash = src;
  1339.     for (bp = src + 1; *bp == '-' || vim_isIDc(*bp); bp++)
  1340.     {
  1341.     if (*bp == '-')
  1342.     {
  1343.         last_dash = bp;
  1344.         if (bp[1] != NUL && bp[2] == '>')
  1345.         ++bp;    /* anything accepted, like <C-?> */
  1346.     }
  1347.     if (bp[0] == 't' && bp[1] == '_' && bp[2] && bp[3])
  1348.         bp += 3;    /* skip t_xx, xx may be '-' or '>' */
  1349.     }
  1350.  
  1351.     if (*bp == '>')    /* found matching '>' */
  1352.     {
  1353.     end_of_name = bp + 1;
  1354.  
  1355.     /* Which modifiers are given? */
  1356.     modifiers = 0x0;
  1357.     for (bp = src + 1; bp < last_dash; bp++)
  1358.     {
  1359.         if (*bp != '-')
  1360.         {
  1361.         bit = name_to_mod_mask(*bp);
  1362.         if (bit == 0x0)
  1363.             break;    /* Illegal modifier name */
  1364.         modifiers |= bit;
  1365.         }
  1366.     }
  1367.  
  1368.     /*
  1369.      * Legal modifier name.
  1370.      */
  1371.     if (bp >= last_dash)
  1372.     {
  1373.         /*
  1374.          * Modifier with single letter, or special key name.
  1375.          */
  1376.         if (modifiers != 0 && last_dash[2] == '>')
  1377.         key = last_dash[1];
  1378.         else
  1379.         key = get_special_key_code(last_dash + 1);
  1380.  
  1381.         /*
  1382.          * get_special_key_code() may return NUL for invalid
  1383.          * special key name.
  1384.          */
  1385.         if (key != NUL)
  1386.         {
  1387.         /*
  1388.          * Only use a modifier when there is no special key code that
  1389.          * includes the modifier.
  1390.          */
  1391.         key = simplify_key(key, &modifiers);
  1392.  
  1393.         /*
  1394.          * Normal Key with modifier: Try to make a single byte code.
  1395.          */
  1396.         if (!IS_SPECIAL(key))
  1397.         {
  1398.             if ((modifiers & MOD_MASK_SHIFT) && isalpha(key))
  1399.             {
  1400.             key = TO_UPPER(key);
  1401.             modifiers &= ~MOD_MASK_SHIFT;
  1402.             }
  1403.             if ((modifiers & MOD_MASK_CTRL)
  1404.                 && ((key >= '?' && key <= '_') || isalpha(key)))
  1405.             {
  1406.             if (key == '?')
  1407.                 key = DEL;
  1408.             else
  1409.                 key &= 0x1f;
  1410.             modifiers &= ~MOD_MASK_CTRL;
  1411.             }
  1412.             if ((modifiers & MOD_MASK_ALT) && key < 0x80)
  1413.             {
  1414.             key |= 0x80;
  1415.             modifiers &= ~MOD_MASK_ALT;
  1416.             }
  1417.         }
  1418.  
  1419.         *modp = modifiers;
  1420.         *srcp = end_of_name;
  1421.         return key;
  1422.         }
  1423.     }
  1424.     }
  1425.     return 0;
  1426. }
  1427.  
  1428. /*
  1429.  * Try to find key "c" in the special key table.
  1430.  * Return the index when found, -1 when not found.
  1431.  */
  1432.     int
  1433. find_special_key_in_table(c)
  1434.     int        c;
  1435. {
  1436.     int        i;
  1437.  
  1438.     for (i = 0; key_names_table[i].name != NULL; i++)
  1439.     if (c == key_names_table[i].key)
  1440.         break;
  1441.     if (key_names_table[i].name == NULL)
  1442.     i = -1;
  1443.     return i;
  1444. }
  1445.  
  1446. /*
  1447.  * Find the special key with the given name (the given string does not have to
  1448.  * end with NUL, the name is assumed to end before the first non-idchar).
  1449.  * If the name starts with "t_" the next two characters are interpreted as a
  1450.  * termcap name.
  1451.  * Return the key code, or 0 if not found.
  1452.  */
  1453.     int
  1454. get_special_key_code(name)
  1455.     char_u  *name;
  1456. {
  1457.     char_u  *table_name;
  1458.     char_u  string[3];
  1459.     int        i, j;
  1460.  
  1461.     /*
  1462.      * If it's <t_xx> we get the code for xx from the termcap
  1463.      */
  1464.     if (name[0] == 't' && name[1] == '_' && name[2] != NUL && name[3] != NUL)
  1465.     {
  1466.     string[0] = name[2];
  1467.     string[1] = name[3];
  1468.     string[2] = NUL;
  1469.     if (add_termcap_entry(string, FALSE) == OK)
  1470.         return TERMCAP2KEY(name[2], name[3]);
  1471.     }
  1472.     else
  1473.     for (i = 0; key_names_table[i].name != NULL; i++)
  1474.     {
  1475.         table_name = key_names_table[i].name;
  1476.         for (j = 0; vim_isIDc(name[j]) && table_name[j] != NUL; j++)
  1477.         if (TO_LOWER(table_name[j]) != TO_LOWER(name[j]))
  1478.             break;
  1479.         if (!vim_isIDc(name[j]) && table_name[j] == NUL)
  1480.         return key_names_table[i].key;
  1481.     }
  1482.     return 0;
  1483. }
  1484.  
  1485.     char_u *
  1486. get_key_name(i)
  1487.     int        i;
  1488. {
  1489.     if (i >= KEY_NAMES_TABLE_LEN)
  1490.     return NULL;
  1491.     return  key_names_table[i].name;
  1492. }
  1493.  
  1494. #ifdef USE_MOUSE
  1495. /*
  1496.  * Look up the given mouse code to return the relevant information in the other
  1497.  * arguments.  Return which button is down or was released.
  1498.  */
  1499.     int
  1500. get_mouse_button(code, is_click, is_drag)
  1501.     int        code;
  1502.     int        *is_click;
  1503.     int        *is_drag;
  1504. {
  1505.     int        i;
  1506.  
  1507.     for (i = 0; mouse_table[i].pseudo_code; i++)
  1508.     if (code == mouse_table[i].pseudo_code)
  1509.     {
  1510.         *is_click = mouse_table[i].is_click;
  1511.         *is_drag = mouse_table[i].is_drag;
  1512.         return mouse_table[i].button;
  1513.     }
  1514.     return 0;        /* Shouldn't get here */
  1515. }
  1516.  
  1517. /*
  1518.  * Return the appropriate pseudo mouse event token (KE_LEFTMOUSE etc) based on
  1519.  * the given information about which mouse button is down, and whether the
  1520.  * mouse was clicked, dragged or released.
  1521.  */
  1522.     int
  1523. get_pseudo_mouse_code(button, is_click, is_drag)
  1524.     int        button;    /* eg MOUSE_LEFT */
  1525.     int        is_click;
  1526.     int        is_drag;
  1527. {
  1528.     int        i;
  1529.  
  1530.     for (i = 0; mouse_table[i].pseudo_code; i++)
  1531.     if (button == mouse_table[i].button
  1532.         && is_click == mouse_table[i].is_click
  1533.         && is_drag == mouse_table[i].is_drag)
  1534.     {
  1535.         return mouse_table[i].pseudo_code;
  1536.     }
  1537.     return (int)KE_IGNORE;        /* not recongnized, ignore it */
  1538. }
  1539. #endif /* USE_MOUSE */
  1540.  
  1541. /*
  1542.  * Return the current end-of-line type: EOL_DOS, EOL_UNIX or EOL_MAC.
  1543.  */
  1544.     int
  1545. get_fileformat(buf)
  1546.     BUF        *buf;
  1547. {
  1548.     int        c = *buf->b_p_ff;
  1549.  
  1550.     if (buf->b_p_bin || c == 'u')
  1551.     return EOL_UNIX;
  1552.     if (c == 'm')
  1553.     return EOL_MAC;
  1554.     return EOL_DOS;
  1555. }
  1556.  
  1557. /*
  1558.  * Set the current end-of-line type to EOL_DOS, EOL_UNIX or EOL_MAC.
  1559.  * Sets both 'textmode' and 'fileformat'.
  1560.  */
  1561.     void
  1562. set_fileformat(t)
  1563.     int        t;
  1564. {
  1565.     switch (t)
  1566.     {
  1567.     case EOL_DOS:
  1568.     set_string_option_direct((char_u *)"ff", -1, (char_u *)FF_DOS, TRUE);
  1569.     curbuf->b_p_tx = TRUE;
  1570.     break;
  1571.     case EOL_UNIX:
  1572.     set_string_option_direct((char_u *)"ff", -1, (char_u *)FF_UNIX, TRUE);
  1573.     curbuf->b_p_tx = FALSE;
  1574.     break;
  1575.     case EOL_MAC:
  1576.     set_string_option_direct((char_u *)"ff", -1, (char_u *)FF_MAC, TRUE);
  1577.     curbuf->b_p_tx = FALSE;
  1578.     break;
  1579.     }
  1580.     check_status(curbuf);
  1581. }
  1582.  
  1583. /*
  1584.  * Return the default fileformat from 'fileformats'.
  1585.  */
  1586.     int
  1587. default_fileformat()
  1588. {
  1589.     switch (*p_ffs)
  1590.     {
  1591.     case 'm':   return EOL_MAC;
  1592.     case 'd':   return EOL_DOS;
  1593.     }
  1594.     return EOL_UNIX;
  1595. }
  1596.  
  1597. /*
  1598.  * Call shell.    Calls mch_call_shell, with 'shellxquote' added.
  1599.  */
  1600.     int
  1601. call_shell(cmd, opt)
  1602.     char_u    *cmd;
  1603.     int        opt;
  1604. {
  1605.     char_u    *ncmd;
  1606.  
  1607.     if (cmd == NULL || *p_sxq == NUL)
  1608.     call_shell_retval = mch_call_shell(cmd, opt);
  1609.     else
  1610.     {
  1611.     ncmd = alloc((unsigned)(STRLEN(cmd) + STRLEN(p_sxq) * 2 + 1));
  1612.     if (ncmd != NULL)
  1613.     {
  1614.         STRCPY(ncmd, p_sxq);
  1615.         STRCAT(ncmd, cmd);
  1616.         STRCAT(ncmd, p_sxq);
  1617.         call_shell_retval = mch_call_shell(ncmd, opt);
  1618.         vim_free(ncmd);
  1619.     }
  1620.     else
  1621.         call_shell_retval = FAIL;
  1622.     }
  1623.     return call_shell_retval;
  1624. }
  1625.  
  1626. /*
  1627.  * VISUAL and OP_PENDING State are never set, they are equal to NORMAL State
  1628.  * with a condition.  This function returns the real State.
  1629.  */
  1630.     int
  1631. get_real_state()
  1632. {
  1633.     if ((State & NORMAL))
  1634.     {
  1635.     if (VIsual_active)
  1636.         return VISUAL;
  1637.     else if (finish_op)
  1638.         return OP_PENDING;
  1639.     }
  1640.     return State;
  1641. }
  1642.